package com.example.game;


/**
 * @author: HanTing Wang
 * @description:
 * @version:
 * @date: 2022/1/21
 */
public abstract class AI {

    public static final int SIDE = 15;
    public static final int BLANK = 0;
    public static final int BLACK = 1;
    public static final int WHITE = 2;

    private static final int[] dx = {1, 0, 1,-1};
    private static final int[] dy = {0, 1, 1, 1};

    private static final int[][] scores =
            {{0, 0, 0},
            {0, 5, 5},
            {5, 8, 100},
            {10, 500, 3000},
            {20, 2500, 300000},
            {1000000, 1000000, 1000000}};

    /**
     * return ai best drop of the color
     *
     * @param arr:
     * @param color:
     * @return int[], length = 2, [x, y]
     */
    public static int[] getBestDrop(int[][] arr, int color) {
        printScores(arr, color);
        return null;
    }

    private static boolean checkBoard(int x, int y) {
        return x >= 0 && x < SIDE && y >= 0 && y < SIDE;
    }

    private static int[] getLine(int[][] arr, int x, int y, int color, int pos) {
        int[] results = new int[5];
        if (!checkBoard(x, y) || arr[y][x] == BLANK) {
            results[0] = 0;
            return results;
        }
        int sum = 1, hx = x + dx[pos], hy = y + dy[pos], lx = x - dx[pos], ly = y - dy[pos];
        for (; checkBoard(hx, hy) && arr[hy][hx] == color; hx += dx[pos], hy += dy[pos]) ++sum;
        for (; checkBoard(lx, ly) && arr[ly][lx] == color; lx -= dx[pos], ly -= dy[pos]) ++sum;
        results[0] = sum;
        results[1] = lx;
        results[2] = ly;
        results[3] = hx;
        results[4] = hy;
        return results;
    }

    private static int evaluate(int[][] arr, int color, int x, int y) {
        int result = 0;
        if (checkBoard(x, y) && (color == BLACK || color == WHITE)) {
            result += 14 - (Math.abs(x - (SIDE >> 1)) + Math.abs(y - (SIDE >> 1)));
            for (int r = 0; r < 4; ++r) {
                int[] line = new int[5];

                int temp = arr[y][x];
                arr[y][x] = color;
                getLine(arr,x, y, color, r);
                arr[y][x] = temp;

                int length = line[0];
                int alive = 0;
                if (checkBoard(line[1], line[2]) && arr[line[2]][line[1]] == BLANK) ++ alive;
                if (checkBoard(line[3], line[4]) && arr[line[4]][line[3]] == BLANK) ++ alive;

                result += scores[length][alive];
                switch(length) {
                    case 5:
                        return result;
                    case 4:
                        break;
                    case 3:
                        if (alive > 0) {
                            int[] tLine = new int[5];
                            if (checkBoard(line[1], line[2]) && arr[line[2]][line[1]] == BLANK) {
                                getLine(arr, line[1]-dx[r], line[2]-dy[r], color, r);
                                result += tLine[0] * 2000;
                            }
                            if (checkBoard(line[3], line[4]) && arr[line[4]][line[3]] == BLANK) {
                                getLine(arr, line[3]-dx[r], line[4]-dy[r], color, r);
                                result += tLine[0] * 2000;
                            }
                        }
                        break;
                    case 2:
                        if (alive > 0) {
                            int[] tLine = new int[5];
                            if (checkBoard(line[1], line[2]) && arr[line[2]][line[1]] == BLANK) {
                                getLine(arr, line[1]-dx[r], line[2]-dy[r], color, r);
                                result += tLine[0] * 1000;
                            }
                            if (checkBoard(line[3], line[4]) && arr[line[4]][line[3]] == BLANK) {
                                getLine(arr, line[3]-dx[r], line[4]-dy[r], color, r);
                                result += tLine[0] * 1000;
                            }
                        }
                        break;
                    case 1:
                        if (alive > 0) {
                            int[] tLine = new int[5];
                            if (checkBoard(line[1], line[2]) && arr[line[2]][line[1]] == BLANK) {
                                getLine(arr, line[1]-dx[r], line[2]-dy[r], color, r);
                                result += tLine[0] * 200;
                            }
                            if (checkBoard(line[3], line[4]) && arr[line[4]][line[3]] == BLANK) {
                                getLine(arr, line[3]-dx[r], line[4]-dy[r], color, r);
                                result += tLine[0] * 200;
                            }
                        }
                        break;
                }
            }
        }
        return result;
    }

    private static void printScores(int[][] arr, int color) {
        for (int i = 0; i < SIDE; ++i) {
            for (int j = 0; j < SIDE; ++j) {
                if (arr[i][j] != BLANK) {
                    System.out.print("\t\t");
                } else {
                    arr[i][j] = color;
                    int score = evaluate(arr, color, j, i);
                    System.out.print(String.format("%7d ", score));
                    arr[i][j] = BLANK;
                }
            }
            System.out.println();
        }
        System.out.println("---------------------------------------------------");
    }

}
